package xyz.xtt.pay.service.order;

import static java.util.stream.Collectors.toList;
import static xyz.xtt.common.asset.AssertUtils.isFalse;
import static xyz.xtt.common.asset.AssertUtils.isNull;
import static xyz.xtt.common.asset.AssertUtils.isTrue;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import com.google.common.primitives.Longs;

import cn.hutool.core.util.IdUtil;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import xyz.xtt.asset.api.enums.GoodsTypeEnum;
import xyz.xtt.equity.api.dto.TblBenefitPackageDto;
import xyz.xtt.exchange.response.AssetAuditResponse;
import xyz.xtt.pay.api.enums.PayOrderBusinessTypeEnum;
import xyz.xtt.pay.api.enums.PayOrderStatusEnum;
import xyz.xtt.pay.client.request.MakeOrderRequest;
import xyz.xtt.pay.constants.ErrorMessage;
import xyz.xtt.pay.constants.PayConstants;
import xyz.xtt.pay.entity.TblBusinessOrder;
import xyz.xtt.pay.exception.ChainException;
import xyz.xtt.pay.service.BusinessOrderOperator;
import xyz.xtt.pay.service.IConfigService;
import xyz.xtt.pay.service.IInnerService;
import xyz.xtt.pay.service.INftOrderService;
import xyz.xtt.pay.service.IPayOrderOperator;
import xyz.xtt.pay.service.ITblBusinessOrderService;

/**
 * 个人铸造V2业务订单操作
 * 
 * @author dale
 * @date 2025/3/17
 **/
@Service
@Slf4j
public class PersonalMintV2BusinessOrderOperator implements BusinessOrderOperator {
	@Autowired
	private INftOrderService nftOrderService;
	@Autowired
	private ITblBusinessOrderService iTblBusinessOrderService;
	@Autowired
	private IInnerService iInnerService;
	@Autowired
	private IPayOrderOperator iPayOrderOperator;
	@Autowired
	private IConfigService iConfigService;

	/**
	 * 是否支持该类型的订单
	 *
	 * @param type
	 * @return
	 */
	@Override
	public boolean canOperateType(PayOrderBusinessTypeEnum type) {
		return Objects.equals(type, PayOrderBusinessTypeEnum.PERSONAL_MINT_V2);
	}

	/**
	 * 创建订单
	 *
	 * @param uid              用户ID
	 * @param makeOrderRequest 创建订单请求
	 * @return 订单
	 */
	@Override
	public TblBusinessOrder makeOrder(String uid, MakeOrderRequest makeOrderRequest) {
		LocalDateTime now = LocalDateTime.now();
		long buyerId = Long.parseLong(uid);
		String orderType = makeOrderRequest.getOrderType();
		long assetAuditId = Long.parseLong(makeOrderRequest.getAssetAuditId());
		AssetAuditResponse auditRecord = iInnerService.assetAuditInfo(assetAuditId);
		isNull(auditRecord, ErrorMessage.ORDER_CREATE_FAILED);
		isFalse(Objects.equals(auditRecord.getAppUserId(), buyerId), ErrorMessage.ORDER_CREATE_FAILED);
		isFalse(!Objects.equals(auditRecord.getResult(), 1) || !Objects.equals(auditRecord.getState(), 0), ErrorMessage.ORDER_CREATE_FAILED);
		GoodsTypeEnum goodsTypeEnum = GoodsTypeEnum.valueOf(makeOrderRequest.getOrderType());
		String goodsId = makeOrderRequest.getAssetAuditId();
		// 检查是否有待支付的订单
		TblBusinessOrder unPayOrder = iTblBusinessOrderService.getUnPayBusinessOrder(buyerId, goodsTypeEnum.getCode(), goodsId);
		if (unPayOrder != null) {
			return unPayOrder;
		}

		BigDecimal benefitCost = BigDecimal.ZERO;
		String packageIds = auditRecord.getPackageIds();
		if (StringUtils.isNotBlank(packageIds)) {
			List<Long> packageIdsWithLong = Arrays.stream(packageIds.split(",")).mapToLong(Longs::tryParse).boxed().collect(toList());
			List<TblBenefitPackageDto> packageDtos = iInnerService.getPackageByIds(packageIdsWithLong);
			isTrue(CollectionUtils.isEmpty(packageDtos), ErrorMessage.ORDER_CREATE_FAILED);
			for (TblBenefitPackageDto packageDto : packageDtos) {
				benefitCost = benefitCost.add(packageDto.getSalePrice());
			}
		}
		benefitCost = benefitCost.multiply(new BigDecimal(auditRecord.getAmount()));

		// 实际需要支付的铸造数量=总铸造数量-消耗的免费铸造数量
		int realPayNum = auditRecord.getAmount() - auditRecord.getRightAmount();
		// 价格计算
		BigDecimal fee = BigDecimal.ZERO;
		if (realPayNum > 0) {
			String priceResult = iConfigService.calculatePersonalMintPrice(realPayNum);
			if (StringUtils.isBlank(priceResult)) {
				log
						.error("PersonalMintV2PayOrderOperator createPayOrder calculatePersonalMintPrice failed. uid:{} " + "param:{} result:{}", uid, JSONUtil
								.toJsonStr(makeOrderRequest), JSONUtil.toJsonStr(priceResult));
				throw new ChainException(ErrorMessage.ORDER_CREATE_FAILED);
			}
			fee = new BigDecimal(priceResult).multiply(new BigDecimal(realPayNum));
		}
		fee = fee.add(benefitCost);
		log
				.info("PersonalMintV2PayOrderOperator createPayOrder calculatePersonalMintPrice success. uid:{} param:{} " + "fee:{}", uid, JSONUtil
						.toJsonStr(makeOrderRequest), fee);
		// 测试用户重置价格
		fee = nftOrderService.testUserResetPrice(buyerId, fee);

		TblBusinessOrder order = new TblBusinessOrder();
		order.setOrderId(IdUtil.getSnowflakeNextId());
		order.setGoodsId(goodsId);
		order.setGoodsType(goodsTypeEnum.getCode());
		order.setGoodsName("铸造：" + auditRecord.getAssetName());
		order.setGoodsImage(auditRecord.getImgPath());
		order.setSellerId(PayConstants.TONGTONG_PLATFROM_USER_ID);
		order.setAppUserId(buyerId);
		order.setBusinessRefId(makeOrderRequest.getAssetAuditId());
		order.setPurchaseNum(1);
		order.setOriginPrice(fee.setScale(2, RoundingMode.HALF_UP));
		order.setRealPrice(order.getOriginPrice());
		order.setTransportPrice(BigDecimal.ZERO);
		order.setDiscountAmount(BigDecimal.ZERO);
		order.setTotalPrice(calculateOrderTotalPrice(order));
		order.setPayAmount(order.getTotalPrice());
		order.setOrderStatus(PayOrderStatusEnum.UN_PAY.getCode());
		order.setOrderTime(now);
		order.setCreateTime(now);
		order.setUpdateTime(now);
		isFalse(iTblBusinessOrderService
				.save(order), ErrorMessage.ORDER_CREATE_FAILED, () -> log.error("save order failed. order:{}", JSONUtil.toJsonStr(order)));
		return order;
	}
}
